/**
 * Copyright @2016-present, Sumscope, Inc.
 * All rights reserved.
 */

const httpProxy = require('http-proxy');
const logger = require('../util/logger');
const {isProd} = require('../util');

const proxy = httpProxy.createProxyServer({});
proxy.on('error', (err) => logger.error(err));

module.exports = (options) => {
  if (!options.pattern) {
    throw new Error('pattern required');
  }
  if (typeof options.pattern === 'string') {
    options.pattern = [options.pattern];
  }
  options.pattern.forEach(pattern => logger.info(`Proxy created ${pattern} -> ${options.target}`));
  // setup events
  const proxyEvents = ['error', 'proxyReq', 'proxyReqWs', 'proxyRes', 'open', 'close'];
  for (let event in options) {
    if (proxyEvents.includes(event)) {
      proxy.on(event, options[event]);
    }
  }
  
  // rewrite path
  let testAndRewriter = (req) => {
    const path = req.url;
    for (let rule of rules) {
      if (rule.regex.test(path)) {
        if (rule.value) {
          req.url = path.replace(rule.regex, rule.value);
        }
        return true;
      }
    }
    return false;
  };
  let rewriteMap = new Map();
  let devSuffix = isProd() ? '' : (options.devRewrite || '')
  options.pattern.forEach(pattern => {
    let [api, business] = pattern.split('/').filter(path => path);
    rewriteMap.set('^' + pattern, {
      regex: new RegExp('^' + pattern),
      value: `/${business}${devSuffix}/${api}/`
    })
  });
  if (options.pathRewrite) {
    for (let key in options.pathRewrite) {
      rewriteMap.set(key, {regex: new RegExp(key), value: options.pathRewrite[key]})
    }
  }
  let rules = [...rewriteMap.values()];
  
  return async (ctx, next) => {
    if (!testAndRewriter(ctx.req)) {
      return await next();
    }
    
    return new Promise((resolve) => {
      options.prepareReq && options.prepareReq(ctx);
      proxy.web(ctx.req, ctx.res, options);
    });
  };
};
